package socket

import (
	"context"
	gorillaWs "github.com/gorilla/websocket"
	"github.com/kataras/iris/v12/websocket"
	"github.com/kataras/neffos"
	"github.com/kataras/neffos/gorilla"
	"gluenet/pkg/apis"
	"net/http"
	"strings"
	"sync"
)

func StatusList(c *apis.StorageContext) {
	var infos []string
	c.StatusSubscriber.Range(func(key, value interface{}) bool {
		infos = append(infos, key.(string))
		return true
	})
	c.WebContext.JSON(apis.ResponseOK(infos))
}

func StatusSocket(c *apis.StorageContext) {
	platform := c.WebContext.URLParam("platform")
	metrics := c.WebContext.URLParam("metric")
	guid := c.WebContext.URLParam("guid")
	object := c.WebContext.URLParam("object")
	child := c.WebContext.URLParam("childname")
	//guid := c.WebContext.URLParam("guid")
	//kind := c.WebContext.URLParam("kind")

	//c.Logger.Debugf("recv")

	var key string
	switch object {
	case "machine":
		key = strings.Join([]string{platform, metrics, guid, child}, "|")
	case "application":
		key = strings.Join([]string{platform, metrics, guid, child}, "|")
	}

	ctx, cancel := context.WithCancel(c.Context)
	var ActuallyNodeCpu = websocket.New(gorilla.Upgrader(gorillaWs.Upgrader{
		CheckOrigin: func(*http.Request) bool { return true },
	}), websocket.Events{
		websocket.OnNativeMessage: func(conn *neffos.NSConn, message neffos.Message) error { return nil },
	})

	ActuallyNodeCpu.OnConnect = func(n *websocket.Conn) error {
		c.Logger.Debugf("OnConnect from server %v %v", n.ID(), "dd")
		//subi, ok := c.Subscriber.Load("kubernetes|container_memory_used_bytes|emojivoto|web-svc")
		subi, ok := c.StatusSubscriber.Load(key)
		if !ok {
			c.Logger.Errorf("metrics not found")
			return nil
		}

		sub := subi.(*sync.Map)
		rchi, _ := sub.LoadOrStore(n.ID(), make(chan string))
		rch := rchi.(chan string)

		for {
			select {
			case data := <-rch:
				n.Write(neffos.Message{
					Body:     []byte(data),
					IsNative: true,
				})
			case <-ctx.Done():
				sub.Delete(n.ID())
				close(rch)
				c.Logger.Debugf("push down %v", n.ID())
				return nil
			}
		}
		return nil
	}

	ActuallyNodeCpu.OnDisconnect = func(n *websocket.Conn) {
		cancel()
		c.Logger.Debugf("Disconnected from server", n.ID())
	}

	ActuallyNodeCpu.OnUpgradeError = func(err error) {
		cancel()
		c.Logger.Debugf("OnUpgradeError from server %v", err)
	}

	websocket.Handler(ActuallyNodeCpu)(c.WebContext)
}

func TotalStatusSocket(c *apis.StorageContext) {
	ctx, cancel := context.WithCancel(c.Context)
	var ActuallyNodeCpu = websocket.New(gorilla.Upgrader(gorillaWs.Upgrader{
		CheckOrigin: func(*http.Request) bool { return true },
	}), websocket.Events{
		websocket.OnNativeMessage: func(conn *neffos.NSConn, message neffos.Message) error { return nil },
	})

	ActuallyNodeCpu.OnConnect = func(n *websocket.Conn) error {
		c.Logger.Debugf("OnConnect from server %v %v", n.ID(), "dd")

		rchi, _ := c.StatusSubscriberTotal.LoadOrStore(n.ID(), make(chan string))
		rch := rchi.(chan string)

		for {
			select {
			case data := <-rch:
				n.Write(neffos.Message{
					Body:     []byte(data),
					IsNative: true,
				})
			case <-ctx.Done():
				c.StatusSubscriberTotal.Delete(n.ID())
				close(rch)
				c.Logger.Debugf("push down %v", n.ID())
				return nil
			}
		}
		return nil
	}

	ActuallyNodeCpu.OnDisconnect = func(n *websocket.Conn) {
		cancel()
		c.Logger.Debugf("Disconnected from server", n.ID())
	}

	ActuallyNodeCpu.OnUpgradeError = func(err error) {
		cancel()
		c.Logger.Debugf("OnUpgradeError from server %v", err)
	}

	websocket.Handler(ActuallyNodeCpu)(c.WebContext)
}
